package org.ipmsg.core.file;

import org.ipmsg.core.*;
import org.ipmsg.core.event.ReceiveProgressListener;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.text.NumberFormat;
import java.util.*;

public class ReceiveFiles extends Thread {

    class Progress extends TimerTask {

        public void run() {
            ReceiveProgressListener listener;
            for (Enumeration em = listeners.elements(); em.hasMoreElements(); listener.receiveProgress(fileID, size, percent)) {
                listener = (ReceiveProgressListener) em.nextElement();
            }
        }

        Progress() {
            super();
        }
    }

    public ReceiveFiles(Message pack, Address address, String path, int fileID, String fileName) {
        this.pack = pack;
        this.address = address;
        this.path = path;
        if (path.endsWith(File.separator)) {
            this.path = path.substring(0, path.length() - 1);
        }
        this.fileID = fileID;
        this.fileName = fileName;
        listeners = new Hashtable();
        attachment = pack.getAttachment();
        numberFormat = NumberFormat.getNumberInstance();
        size = "";
        percent = 0;
        t = new Timer(true);
    }

    @Override
    public void run() {
        Socket conn = null;
        try {
            initState((new StringBuilder(String.valueOf(path))).append(File.separator).append(fileName).toString());
            conn = new Socket(address.getInetAddress(), address.getPort());
            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            DataInputStream dis = new DataInputStream(conn.getInputStream());
            Progress p = new Progress();
            t.scheduleAtFixedRate(p, 0L, 300L);
            long type = attachment.getFileAttribute(fileID) & 255L;
            switch ((int) type) {
                case 1: // '\001'
                    saveFile(dos, dis);
                    break;

                case 2: // '\002'
                    saveDir(dos, dis);
                    break;
            }
            dos.close();
            dis.close();
            conn.close();
            changeState(1);
        } catch (Exception ex) {
            changeState(2);
            ex.printStackTrace();
        } finally {
            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (Exception exception1) {
            }
            if (stop) {
                changeState(3);
            }
            try {
                Thread.sleep(500L);
                t.cancel();
            } catch (Exception exception2) {
            }
        }
    }

    public byte[] getRequestHeader(long command) {
        StringBuffer header = new StringBuffer();
        header.append(Long.toString(1L)).append(":");
        header.append(Long.toString(System.currentTimeMillis() / 1000L)).append(":");
        header.append(System.getProperty("user.name", "No Name")).append(":");
        String host = "";
        try {
            host = InetAddress.getLocalHost().getHostName();
        } catch (Exception exception) {
        }
        header.append(host).append(":");
        header.append(Long.toString(command)).append(":");
        header.append(Long.toHexString(pack.getSerial())).append(":");
        header.append(Long.toHexString(attachment.getFileID(fileID))).append(":");
        header.append(Long.toHexString(0L)).append(":");
        return header.toString().getBytes();
    }

    public void saveFile(DataOutputStream dos, DataInputStream dis)
            throws Exception {
        dos.write(getRequestHeader(Protocol.GETFILEDATA));
        int read = 0;
        long readCount = 0L;
        long fileSize = attachment.getFileSize(fileID);
        byte buffer[] = new byte[0x10000];
        File file = new File((new StringBuilder(String.valueOf(path))).append(File.separator).append(fileName).toString());
        FileOutputStream out = new FileOutputStream(file);
        while (!stop && readCount < fileSize) {
            read = dis.read(buffer, 0, (int) Math.min(fileSize - readCount, buffer.length));
            if (read < 0) {
                break;
            }
            readCount += read;
            out.write(buffer, 0, read);
            progress(numberFormat.format(readCount / 1024L), Integer.parseInt(numberFormat.format((readCount * 100L) / fileSize)));
        }
        out.close();
        if ((attachment.getFileAttribute(fileID) & Protocol.FILE_RONLYOPT) != 0L) {
            file.setReadOnly();
        }
        file.setLastModified(attachment.getFileLastModified(fileID));
    }

    public void saveDir(DataOutputStream dos, DataInputStream dis)
            throws Exception {
        String filePath;
        long allFileSize;
        dos.write(getRequestHeader(Protocol.GETDIRFILES));
        filePath = path;
        allFileSize = 0L;

        while (!stop) {
            long fileSize;
            byte headerSize[] = new byte[4];
            dis.read(headerSize);
            int len = (int) Long.parseLong(new String(headerSize, "GBK"), 16) - 4;
            headerSize = new byte[len];
            dis.read(headerSize);
            StringTokenizer tokenizer = new StringTokenizer(new String(headerSize, "GBK"), ":", false);
            String folderName = tokenizer.nextToken();
            fileSize = Long.parseLong(tokenizer.nextToken(), 16);
            long fileAttribute = Long.parseLong(tokenizer.nextToken(), 16);
            long fileLastModified = Long.parseLong(tokenizer.nextToken().substring(3), 16) * 1000L;
            long type = fileAttribute & 255L;
            switch ((int) type) {
                default: {
                    continue; /* Loop/switch isn't completed */
                }

                case 2: // '\002'
                {
                    if (filePath.equalsIgnoreCase(path)) {
                        folderName = fileName;
                    }
                    filePath = (new StringBuilder(String.valueOf(filePath))).append(File.separator).append(folderName).toString();
                    File file = new File(filePath);
                    file.mkdirs();
                    break;
                }

                case 1: // '\001'
                {
                    int read = 0;
                    long readCount = 0L;
                    byte buffer[] = new byte[0x10000];
                    File file = new File((new StringBuilder(String.valueOf(filePath))).append(File.separator).append(folderName).toString());
                    FileOutputStream out = new FileOutputStream(file);
                    while (!stop && readCount < fileSize) {
                        read = dis.read(buffer, 0, (int) Math.min(fileSize - readCount, buffer.length));
                        if (read < 0) {
                            break;
                        }
                        out.write(buffer, 0, read);
                        readCount += read;
                        allFileSize += read;
                        progress(numberFormat.format(allFileSize / 1024L), 0);
                    }
                    out.close();
                    if ((fileAttribute & Protocol.FILE_RONLYOPT) != 0L) {
                        file.setReadOnly();
                    }
                    file.setLastModified(fileLastModified);
                    break;
                }

                case 3: // '\003'
                {
                    File file = new File(filePath);
                    file.mkdirs();
                    if ((fileAttribute & Protocol.FILE_RONLYOPT) != 0L) {
                        file.setReadOnly();
                    }
                    file.setLastModified(fileLastModified);
                    filePath = file.getParent();
                    if (filePath.endsWith(File.separator)) {
                        filePath = filePath.substring(0, filePath.length() - 1);
                    }
                    if (!filePath.equalsIgnoreCase(path)) {
                        break;
                    }
                    break; /* Loop/switch isn't completed */
                }
            }
            dis.skip(fileSize);
        }
    }

    public void breakSave() {
        stop = true;
    }

    public void addReceiveProgressListener(ReceiveProgressListener listener) {
        listeners.put(listener, listener);
    }

    public void removeReceiveProgressListener(ReceiveProgressListener listener) {
        listeners.remove(listener);
    }

    public void initState(String path) {
        ReceiveProgressListener listener;
        for (Enumeration em = listeners.elements(); em.hasMoreElements(); listener.receiveInitState(fileID, path)) {
            listener = (ReceiveProgressListener) em.nextElement();
        }
    }

    public void changeState(int state) {
        ReceiveProgressListener listener;
        for (Enumeration em = listeners.elements(); em.hasMoreElements(); listener.receiveChangeState(fileID, state)) {
            listener = (ReceiveProgressListener) em.nextElement();
        }
    }

    public void progress(String size, int percent) {
        this.size = size;
        this.percent = percent;
    }
    private Message pack;
    private Address address;
    private Attachment attachment;
    private Hashtable listeners;
    private boolean stop;
    private String path;
    private int fileID;
    private String fileName;
    private NumberFormat numberFormat;
    private String size;
    private int percent;
    private Timer t;
}